package com.dykj.fireFighting.server.base.video.service.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dykj.fireFighting.api.base.system.entity.SysDirectory;
import com.dykj.fireFighting.api.base.system.service.ISysDirectoryService;
import com.dykj.fireFighting.api.base.video.dto.VideoDto;
import com.dykj.fireFighting.api.base.video.entity.Video;
import com.dykj.fireFighting.api.base.video.entity.VideoDevice;
import com.dykj.fireFighting.api.base.video.service.IVideoDeviceService;
import com.dykj.fireFighting.api.base.video.service.IVideoService;
import com.dykj.fireFighting.api.base.video.vo.VideoDeviceVo;
import com.dykj.fireFighting.api.base.video.vo.VideoPlayVo;
import com.dykj.fireFighting.api.base.video.vo.VideoVo;
import com.dykj.fireFighting.common.core.service.impl.BaseServiceImpl;
import com.dykj.fireFighting.common.core.utils.HttpClientResult;
import com.dykj.fireFighting.common.core.utils.HttpUtil;
import com.dykj.fireFighting.common.core.utils.UUIDUtils;
import com.dykj.fireFighting.common.core.vo.LoginUserVo;
import com.dykj.fireFighting.common.core.vo.PageVo;
import com.dykj.fireFighting.common.core.vo.TreeVo;
import com.dykj.fireFighting.common.starter.redis.service.RedisService;
import com.dykj.fireFighting.server.base.video.mapper.VideoMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 监控设备管理
 *
 * @Author hxb
 * @Date 2021-06-25 08:42:12
 */
@Slf4j
@DubboService
@Transactional(rollbackFor = Exception.class)
public class VideoServiceImpl extends BaseServiceImpl<VideoMapper, Video> implements IVideoService {

    @Autowired
    private ISysDirectoryService sysDirectoryService;
    @Autowired
    private RedisService redisService;

    @Autowired
    private IVideoDeviceService videoDeviceService;

    @Value("${YS.HOSTADDRESS}")
    private String hostAddress;
    @Value("${YS.DEVONLY}")
    private String devonly;


    @Override
    public PageVo<VideoVo> queryVideoList(VideoDto videoDto, LoginUserVo loginUserVo) {
        Map<String, Object> params = new HashMap<>();
        if (2 == loginUserVo.getEnterpriseType()) {
            List<SysDirectory> childSysDirectoryList = new ArrayList<SysDirectory>();
            SysDirectory sysDirectory = sysDirectoryService.queryByCode(videoDto.getAreaCode());
            childSysDirectoryList.add(sysDirectory);
            childSysDirectoryList = sysDirectoryService.getChildSysDirectoryList(childSysDirectoryList, videoDto.getAreaCode());

            params.put("sysDirectoryList", childSysDirectoryList);
            params.put("bindingCode", videoDto.getBindingCode());
        } else if (0 == loginUserVo.getEnterpriseType()) {
            videoDto.setUnitId(loginUserVo.getEnterpriseId().toString());
        }

        params.put("unitId", videoDto.getUnitId());
        params.put("videoName",videoDto.getVideoName());
        params.put("vedioType",videoDto.getVedioType());
        Page page = new Page();
        // 设置当前页码
        page.setCurrent(videoDto.getPage());
        // 设置页大小
        page.setSize(videoDto.getLimit());
        return new PageVo<VideoVo>(this.baseMapper.queryVideoList(page, params));
    }

    @Override
    public List<VideoVo> queryVideoPositionList(String unitId) {


        return (this.baseMapper.queryVideoPositionList(unitId));
    }

    @Override
    public VideoPlayVo videoPlay(String id) {
        Video video = this.baseMapper.selectById(id);
        String accessToken = getAccessToken(video.getVideoSerial(), video.getAppkey(), video.getAppsecret());

        VideoPlayVo videoPlayVo = new VideoPlayVo();
        videoPlayVo.setVideoSerial(video.getVideoSerial());
        videoPlayVo.setChannel(video.getChannel());
        videoPlayVo.setAccessToken(accessToken);
        videoPlayVo.setUserName(video.getUserName());
        videoPlayVo.setPassword(video.getPassword());
        videoPlayVo.setIp(video.getIp());
        videoPlayVo.setPort(video.getPort());
        videoPlayVo.setVedioType(video.getVedioType());
        videoPlayVo.setId(video.getId());
        videoPlayVo.setVideoName(video.getVideoName());
        videoPlayVo.setSubtype(video.getSubtype());
        return videoPlayVo;
    }


    /**
     * 获取AccessToken 并设置redis值
     *
     * @param gridCode
     * @return
     */
    public String getAccessToken(String gridCode, String appKey, String appSecret) {
        //从redis中获取token
        String accessToken = (String) redisService.get("AccessToken_" + gridCode);
        if (StringUtils.isBlank(accessToken)) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("appKey", appKey);
            params.put("appSecret", appSecret);
            HttpClientResult result = null;
            try {
                result = HttpUtil.postWithForm(hostAddress, null, params);
                if (!result.isSuccess()) {
                    log.error("{}调用发生异常,result:{}", hostAddress, result);
                } else {
                    if (StringUtils.isNotBlank(result.getData())) {
                        String res = result.getData().substring(result.getData().indexOf("{"));
                        JSONObject resultObj = JSONUtil.parseObj(res);
                        String code = (String) resultObj.get("code");
                        String msg = (String) resultObj.get("msg");
                        if ("200".equals(code)) {
                            JSONObject dataObj = JSONUtil.parseObj(resultObj.get("data"));
                            accessToken = (String) dataObj.get("accessToken");
                            Long expireTime = (Long) dataObj.get("expireTime");
                            Long now = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
                            // 有效期 = 过期时间 - 现在 - 一天
                            //Long expire = expireTime - now - (60 * 60 * 24);
                            Long expire = 259200L;
                            log.info("AccessToken信息:AccessToken_" + gridCode + ",过期时间:" + expire);
                            // 普通缓存放入并设置时间
                            redisService.set("AccessToken_" + gridCode, accessToken, expire);
                        } else {
                            log.info("返回码：" + code);
                            log.info("返回信息：" + msg);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return accessToken;
    }

    /**
     * 通过token和序列号获取设备
     *
     * @param accessToken
     * @param videoSerial
     * @return
     */
    private List<VideoPlayVo> getVideoList(String accessToken, String videoSerial) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("accessToken", accessToken);
        params.put("deviceSerial", videoSerial);
        HttpClientResult result = null;
        try {
            result = HttpUtil.postWithForm(devonly, null, params);
            if (!result.isSuccess()) {
                log.error("{}调用发生异常,result:{}", hostAddress, result);
            } else {
                if (StringUtils.isNotBlank(result.getData())) {
                    String res = result.getData().substring(result.getData().indexOf("{"));
                    JSONObject resultObj = JSONUtil.parseObj(res);
                    String code = (String) resultObj.get("code");
                    String msg = (String) resultObj.get("msg");
                    if ("200".equals(code)) { // 成功时解析json
                        JSONArray entity = JSONUtil.parseArray(resultObj.get("data"));
                        // 转换为video实体
                        //List<VideoPlayVo> videoPlayVoList = JSONArray.toList(entity, new VideoPlayVo(), new JsonConfig());
                    } else {
                        log.info("返回码：" + code);
                        log.info("返回信息：" + msg);
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取列表出错");
        }
        return null;
    }

    @Transactional
    @Override
    public Boolean insertVideo(VideoDeviceVo videoDeviceVo) {

        Video video = new Video();
        BeanUtils.copyProperties(videoDeviceVo, video);
        String tempId = UUIDUtils.get32UUID();
        video.setId(tempId);
        log.info("摄像头写入数据：{}", video.toString());
        save(video);
        for (int i = 0; i < videoDeviceVo.getDevice().size(); i++) {
            VideoDevice videoDevice = new VideoDevice();
            videoDevice.setDeviceId(videoDeviceVo.getDevice().get(i));
            videoDevice.setVideoId(tempId);
            videoDevice.setType(0);
            videoDevice.setId(UUIDUtils.get32UUID());
            videoDeviceService.save(videoDevice);
        }
        for (int i = 0; i < videoDeviceVo.getDeviceTradition().size(); i++) {
            VideoDevice videoDevice = new VideoDevice();
            videoDevice.setDeviceId(videoDeviceVo.getDeviceTradition().get(i));
            videoDevice.setVideoId(tempId);
            videoDevice.setType(1);
            videoDevice.setId(UUIDUtils.get32UUID());
            videoDeviceService.save(videoDevice);
        }
        return true;
    }

    @Transactional
    @Override
    public Boolean updateVideo(VideoDeviceVo videoDeviceVo) {
        //修改
        Video video = new Video();
        BeanUtils.copyProperties(videoDeviceVo, video);

        log.info("摄像头修改数据：{}", video.toString());
        updateById(video);
        //删除中间设备表数据
        videoDeviceService.delByVideoId(videoDeviceVo.getId());
        //写入中间设备表的数据
        String tempId = videoDeviceVo.getId();
        for (int i = 0; i < videoDeviceVo.getDevice().size(); i++) {
            VideoDevice videoDevice = new VideoDevice();
            videoDevice.setDeviceId(videoDeviceVo.getDevice().get(i));
            videoDevice.setVideoId(tempId);
            videoDevice.setType(0);
            videoDevice.setId(UUIDUtils.get32UUID());
            videoDeviceService.save(videoDevice);
        }
        for (int j = 0; j < videoDeviceVo.getDeviceTradition().size(); j++) {
            VideoDevice videoDevice = new VideoDevice();
            videoDevice.setDeviceId(videoDeviceVo.getDeviceTradition().get(j));
            videoDevice.setVideoId(tempId);
            videoDevice.setType(1);
            videoDevice.setId(UUIDUtils.get32UUID());
            videoDeviceService.save(videoDevice);

        }
        return true;

    }

    @Override
    public TreeVo getVideoTree(String unitId) {
        return this.baseMapper.queryVideoTree(unitId);
    }


}
